package com.jmoto.android.test;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.jmoto.android.test.helpers.MapOverlayItem;
import com.jmoto.android.test.views.MapPopUp;
import com.quickblox.core.QBCallback;
import com.quickblox.core.result.Result;
import com.quickblox.module.locations.QBLocations;
import com.quickblox.module.locations.model.QBLocation;
import com.quickblox.module.locations.result.QBLocationPagedResult;

public class MapViewActivity  extends MapActivity {

	private MapView mapView;
    List<Address> addressList;
    MapController mapController;
    private Drawable marker;
    private WhereAmI ownOverlay;
    private MapPopUp mapPopUp;
    private TimerTask task;
    private Timer timer;
    private ProgressBar mapUpdateProgress;
    private Thread processLocationsDataThread;
	public static final int MAP_CHECK_OWN_POSITION_PERIOD = 1000 * 60 * 2; // 2 min
	public static final int MAP_UPDATE_PERIOD = 1000 * 60 * 3; // 3 m
	
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map_view);
        
        
        // Init Map
        initMapView();


        // init progress wheel
        mapUpdateProgress = (ProgressBar) findViewById(R.id.mapUpdate_progressBar);

        // init map popup
        mapPopUp = new MapPopUp(this, (ViewGroup) mapView.getParent());


        // get a latitude and a longitude of the current user
        LocationManager locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        LocationListener locListener = new LocationListener() {

            @Override
            public void onStatusChanged(String provider, int status,
                    Bundle extras) {
                Log.i("onStatusChanged", provider + String.valueOf(status));
            }

            @Override
            public void onProviderEnabled(String provider) {
                Log.i("onProviderEnabled", provider);
            }

            @Override
            public void onProviderDisabled(String provider) {
            	//QBU
            }

            // if a location of the device will be changed,
            // send the data on the server
            @Override
            public void onLocationChanged(Location location) {
/*                if (location != null && Store.getInstance().getCurrentUser() != null) {

                    Log.i("onLocationChanged", "onLocationChanged");

                    // save current location
                    Store.getInstance().setCurrentLocation(location);

                    String lat = Double.toString(location.getLatitude());
                    String lng = Double.toString(location.getLongitude());

                    // create entity for current user
                    List<NameValuePair> formparamsGeoUser = new ArrayList<NameValuePair>();
                    formparamsGeoUser.add(new BasicNameValuePair(
                            "geo_data[latitude]", lat));
                    formparamsGeoUser.add(new BasicNameValuePair(
                            "geo_data[longitude]", lng));
                    if (Store.getInstance().getCurrentStatus() != null) {
                        formparamsGeoUser.add(new BasicNameValuePair(
                                "geo_data[status]", Store.getInstance().getCurrentStatus()));
                    }
                    formparamsGeoUser.add(new BasicNameValuePair(
                            "token", Store.getInstance().getAuthToken()));

                    UrlEncodedFormEntity postEntityGeoDataUser = null;
                    try {
                        postEntityGeoDataUser = new UrlEncodedFormEntity(
                                formparamsGeoUser, "UTF-8");
                    } catch (UnsupportedEncodingException e1) {
                        e1.printStackTrace();
                    }

                    //
                    // make query
                    Query.performQueryAsync(QueryMethod.Post,
                            QBQueries.CREATE_GEODATA_QUERY,
                            postEntityGeoDataUser, null, MapViewActivity.this,
                            QBQueries.QBQueryType.QBQueryTypeCreateGeodata);

                    Log.i("SEND OWN LOCATION ON THE SERVER", "ON");
                } else {
                    Log.i("SEND OWN LOCATION ON THE SERVER", "OFF");
                }
*/

            }
        };

        List<String> providers = locManager.getProviders(true);
        for (String provider : providers) {

            // registration of the LocationListener.
            locManager.requestLocationUpdates(provider, MAP_CHECK_OWN_POSITION_PERIOD,
                    10, locListener);

            
            
            //Store.getInstance().setCurrentLocation(locManager.getLastKnownLocation(provider));
        }

        marker = getResources().getDrawable(R.drawable.map_marker_other);
        marker.setBounds(0, 0, marker.getIntrinsicWidth(),
                marker.getIntrinsicHeight());
    }
	

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_map_view, menu);
        return true;
    }
    
    private void initMapView() {
        mapView = (MapView) findViewById(R.id.mapview);
        mapController = mapView.getController();
        mapView.setSatellite(true);
        mapView.setBuiltInZoomControls(true);
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        
        startTimer();

        // read a value which is established from CheckBoxPreference
        
        //if (Store.getInstance().getCurrentUser() != null) {
            initMyLocation();
        //}else if (ownOverlay != null){
            //mapView.getOverlays().remove(ownOverlay);
            //ownOverlay = null;
        //}
    }
    
    private void initMyLocation() {
        if(ownOverlay != null){
            return;
        }
        
        ownOverlay = new WhereAmI(this, mapView);
        // to begin follow for the updates of the location
        ownOverlay.enableMyLocation();
        ownOverlay.enableCompass(); // it's no works in the emulator
        ownOverlay.runOnFirstFix(new Runnable() {

            @Override
            public void run() {
                // Show current location and change a zoom
                mapController.setZoom(2);

                if (ownOverlay.getMyLocation() != null) {
                    mapController.animateTo(ownOverlay.getMyLocation());
                }
            }
        });
        mapView.getOverlays().add(ownOverlay);
    }
    
    public void startTimer() {
        timer = new Timer();
        task = new TimerTask() {

            @Override
            public void run() {
                updateMap();
            }
        };

        // each 1 min to do
        timer.schedule(task, 0, MAP_UPDATE_PERIOD);
    }
    
    // update map query
    private void updateMap() {
        if (mapUpdateProgress.getVisibility() == View.VISIBLE) {
            return;
        }

        // show progress wheel
        MapViewActivity.this.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                mapUpdateProgress.setVisibility(View.VISIBLE);
                getAppLocations();
            }
        });

        
    }
    
    
    private void getAppLocations(){
    	
    	final List<MapOverlayItem> locationsList = new ArrayList<MapOverlayItem>();

        processLocationsDataThread = new Thread(new Runnable() {

            public void run() {

            	
            	QBLocations.getLocations(new QBCallback() {
            	    @Override
            	    public void onComplete(Result result) {
            	        // check if request has been successful
            	        // and result doesn't contain errors
            	        if (result.isSuccess()) {
            	            // expect to get QBUserResult instance
            	            QBLocationPagedResult locationResult = (QBLocationPagedResult) result;
            	            ArrayList<QBLocation> locations = locationResult.getLocations();
            	            for (QBLocation qbLocation : locations) {
            	            	final MapOverlayItem overlayItem = new MapOverlayItem(new GeoPoint(qbLocation.getLatitude().intValue() , qbLocation.getLongitude().intValue()), "", "");
                                overlayItem.setUserStatus(qbLocation.getStatus());
                                overlayItem.setUserName(" -" +  qbLocation.getUserId());
                                locationsList.add(overlayItem);
							}
            	            final ShowAllUsers whereAreUsers = new ShowAllUsers(marker, locationsList);
            	            // update map
                   	        // add overlays
                            mapView.getOverlays().clear();
                            mapView.getOverlays().add(whereAreUsers);
                            /*if(ownOverlay != null){
                                mapView.getOverlays().add(ownOverlay);
                            }*/

                            mapView.invalidate();

                            mapUpdateProgress.setVisibility(View.GONE);

            	        } else {
            	            // otherwise handle error case
            	        }
            	    }
            	});
            }
        });

        processLocationsDataThread.start();

        	
    }
    
    



	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}
	
	
	// Other Users overlays
    class ShowAllUsers extends ItemizedOverlay<MapOverlayItem> {

        private List<MapOverlayItem> locations = new ArrayList<MapOverlayItem>();
        private Drawable marker;

        public ShowAllUsers(Drawable marker, List<MapOverlayItem> overlayItems) {
            super(marker);

            this.marker = marker;

            // populate items
            for (MapOverlayItem overlayItem : overlayItems) {
                locations.add(overlayItem);
                populate();
            }
        }

        // a shadow of the marker
        @Override
        public void draw(Canvas canvas, MapView mapView, boolean shadow) {
            super.draw(canvas, mapView, shadow);
            boundCenterBottom(marker);
        }

        @Override
        protected MapOverlayItem createItem(int i) {
            return locations.get(i);
        }

        @Override
        public int size() {
            return locations.size();
        }

        // tab on marker
        @Override
        protected boolean onTap(int i) {

            MapOverlayItem item = (MapOverlayItem) getItem(i);

            // set data
            mapPopUp.setData(item.getUserName(), item.getUserFullName(), item.getUserStatus());

            // show popup
            mapPopUp.show();

            return true;
        }
    }

    // Current User overlay
    public class WhereAmI extends MyLocationOverlay {

        private Context mContext;
        private float mOrientation;
        private Rect markerRect;

        public WhereAmI(Context context, MapView mapView) {
            super(context, mapView);
            mContext = context;
        }

        @Override
        protected void drawMyLocation(Canvas canvas, MapView mapView, Location lastFix, GeoPoint myLocation, long when) {
            // translate the GeoPoint to screen pixels
            Point screenPts = mapView.getProjection().toPixels(myLocation, null);

            // create a rotated copy of the marker
            Bitmap arrowBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.map_marker_my);
            Matrix matrix = new Matrix();
            matrix.postRotate(mOrientation);
            Bitmap rotatedBmp = Bitmap.createBitmap(
                    arrowBitmap,
                    0, 0,
                    arrowBitmap.getWidth(),
                    arrowBitmap.getHeight(),
                    matrix,
                    true);
            // add the rotated marker to the canvas
            canvas.drawBitmap(
                    rotatedBmp,
                    screenPts.x - (rotatedBmp.getWidth() / 2),
                    screenPts.y - (rotatedBmp.getHeight() / 2),
                    null);

            markerRect = new Rect(screenPts.x - (rotatedBmp.getWidth() / 2), screenPts.y - (rotatedBmp.getHeight() / 2),
                    screenPts.x + (rotatedBmp.getWidth() / 2), screenPts.y + (rotatedBmp.getHeight() / 2));

            rotatedBmp.recycle();
        }

        public void setOrientation(float newOrientation) {
            mOrientation = newOrientation;
        }

        @Override
        public boolean onTap(GeoPoint p, MapView map) {

            Point tapPts = mapView.getProjection().toPixels(p, null);

            if (markerRect == null || tapPts == null) {
                return false;
            }

            if (!markerRect.contains(tapPts.x, tapPts.y)) {
                return false;
            }

            // show popup data
            /*String status = Store.getInstance().getCurrentStatus();
            if (status == null) {
                status = "<empty>";
            }
            mapPopUp.setData(Store.getInstance().getCurrentUser().findChild("login").getText(),
                    Store.getInstance().getCurrentUser().findChild("full-name").getText(), status);

            // show popup
            mapPopUp.show();
*/
            return true;
        }
    } 
}
